﻿Imports System.Drawing
Imports System.Windows.Forms

Public Class Form7

    Private Sub scan()
        vertexList.Items.Clear()
        Dim bp As Bitmap = New Bitmap(PictureBox1.Image)
        Dim s As New Shape
        Dim backColor As Color
        backColor = bp.GetPixel(0, 0)
        Dim detected As Boolean = False

        Dim j As Integer = 0
        While j < bp.Height AndAlso Not detected
            Dim i As Integer = 0
            While i < bp.Width AndAlso Not detected
                If Not bp.GetPixel(i, j).Equals(backColor) Then
                    s.Inside = bp.GetPixel(i, j)
                    Dim v As New Vertex(i, j)
                    s.Addvert(v)
                    detect(v, s, bp)
                    detected = True
                End If
                i += 1
            End While
            j += 1
        End While

        Dim verts As New ArrayList
        verts = s.Getvert

        Dim prv As Vertex

        For k As Integer = 0 To s.GetCount() - 1


            prv = DirectCast(verts(k), Vertex)


            vertexList.Items.Add(prv.X.ToString() & "," & prv.Y.ToString())
        Next

        Me.Cursor = Cursors.[Default]

    End Sub

    Private Sub OpenFileDialog1_FileOk(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
        PictureBox1.Load(OpenFileDialog1.FileName)
    End Sub

    Private Sub detect(v As Vertex, s As Shape, b As Bitmap)
        Dim dy As Single = 1, trans_x As Single, trans_y As Single, dx As Single = 1.0F
        Dim directed As Integer = 1, transition As Integer = 3

        Dim steps As Integer = 0

        Dim slopes As New Queue()
        ' slopes
        Dim las5 As New Queue()
        'last 10
        Dim directs As New Queue()
        'directions
        Dim first As New Vertex(v.X, v.Y)
        'first one
        Dim pr As New Vertex(v.X, v.Y)

        Dim prev As New Vertex(v.X, v.Y)

        Dim tx As Integer = 0, ty As Integer = 0

        While True
            Dim color As New ArrayList()
            Dim coods As New ArrayList()
            Dim newpresent As Integer = 0
            Dim is90 As Boolean = False

            For i As Integer = -1 To 1

                color.Add(b.GetPixel(v.X - 1, v.Y + i))
                coods.Add(New Vertex(v.X - 1, v.Y + i))
                

            Next

            color.Add(b.GetPixel(v.X, v.Y + 1))
            coods.Add(New Vertex(v.X, v.Y + 1))

            For i As Integer = 1 To -2 + 1 Step -1

                color.Add(b.GetPixel(v.X + 1, v.Y + i))
                coods.Add(New Vertex(v.X + 1, v.Y + i))
                

            Next

            color.Add(b.GetPixel(v.X, v.Y - 1))
            coods.Add(New Vertex(v.X, v.Y - 1))

            Dim present As Integer = (directed + 1) Mod 8
            Dim c As New Color()

            Do
                c = DirectCast(color(present), Color)
                If c.Equals(s.Inside) Then
                    Exit Do
                End If
                present = (present + 1) Mod 8
            Loop While present <> directed

            pr = DirectCast(coods(present), Vertex)
            steps += 1


            If first.X = pr.X AndAlso first.Y = pr.Y Then
                Exit While
            End If

            dx = CSng(v.X - pr.X)
            dy = v.Y - pr.Y

            If dy < 0 Then
                dy = -dy
            End If

            tx += CInt(dx)
            ty += CInt(dy)

            If tx = 1 OrElse ty = 1 Then
                newpresent = present
            End If

            trans_x = CSng(prev.X - pr.X)

            If trans_x < 0 Then
                trans_x = -trans_x
            End If

            trans_y = CSng(prev.Y - pr.Y)

            If trans_y < 0 Then
                trans_y = -trans_y
            End If

            If trans_x > trans_y Then
                transition = 0
            ElseIf trans_x < trans_y Then
                transition = 1
            Else
                transition = 2
            End If

            If (transition = 1 AndAlso dy = 1) OrElse (transition = 0 AndAlso dx = 1) Then
                tx = 0
                ty = 0
            End If

            Dim rx, ry As Integer

            If transition = 0 AndAlso ty = 2 Then
                If (pr.Y - prev.Y) < 0 Then
                    ry = -2
                Else
                    ry = 2
                End If

                s.Addvert(New Vertex(pr.X, pr.Y + ry))
                prev = New Vertex(pr.X, pr.Y + ry)
                present = newpresent
                v = New Vertex(pr.X, pr.Y + ry)
                is90 = True
            ElseIf transition = 1 AndAlso tx = 2 Then
                If (pr.X - prev.X) > 0 Then
                    rx = -2
                Else
                    rx = 2
                End If
                s.Addvert(New Vertex(pr.X + rx, pr.Y))
                prev = New Vertex(pr.X + rx, pr.Y)
                present = newpresent
                v = New Vertex(pr.X + rx, pr.Y)
                is90 = True
            ElseIf Not is90 Then

                If (dx = 1 AndAlso transition = 1) OrElse (dy = 1 AndAlso transition = 0) OrElse ((dx = 1 OrElse dy = 1) AndAlso transition = 2) Then
                    If slopes.Count = 10 Then
                        slopes.Dequeue()
                        las5.Dequeue()
                        directs.Dequeue()

                        Dim sl As Single
                        'present slope
                        sl = CSng(pr.Y - prev.Y) / (pr.X - prev.X)

                        If sl > 5 Then
                            sl = CSng(Math.Round(sl, 0))
                        Else
                            sl = CSng(Math.Round(sl, 3))
                        End If

                        slopes.Enqueue(sl)
                        las5.Enqueue(pr)
                        directs.Enqueue(present)

                        If slopes.Count = 0 Then
                            Dim flag As Integer = 0
                            Dim a As Object() = New Object(9) {}

                            a = slopes.ToArray()

                            If CSng(a(0)) > CSng(a(1)) AndAlso (CSng(a(1)) > CSng(a(2))) AndAlso CSng(a(2)) > CSng(a(3)) AndAlso CSng(a(3)) > CSng(a(4)) AndAlso CSng(a(4)) > CSng(a(5)) AndAlso CSng(a(5)) > CSng(a(6)) AndAlso CSng(a(6)) > CSng(a(7)) AndAlso CSng(a(7)) > CSng(a(8)) AndAlso CSng(a(8)) > CSng(a(9)) Then
                                flag = 1
                            End If
                            If CSng(a(0)) < CSng(a(1)) AndAlso CSng(a(1)) < CSng(a(2)) AndAlso CSng(a(2)) < CSng(a(3)) AndAlso CSng(a(3)) < CSng(a(4)) AndAlso CSng(a(4)) < CSng(a(5)) AndAlso CSng(a(5)) < CSng(a(6)) AndAlso CSng(a(6)) < CSng(a(7)) AndAlso CSng(a(7)) < CSng(a(8)) AndAlso CSng(a(8)) < CSng(a(9)) Then
                                flag = 1
                            End If
                            If flag = 1 Then
                                'if new vertex detected


                                While slopes.Count <> 0


                                    slopes.Dequeue()

                                    If las5.Count <> 0 Then


                                        las5.Dequeue()


                                        directs.Dequeue()
                                    End If

                                    If las5.Count = 7 Then


                                        present = CInt(directs.Peek())



                                        pr = DirectCast(las5.Peek(), Vertex)
                                        prev = DirectCast(las5.Peek(), Vertex)

                                    End If
                                End While

                                s.Addvert(pr)

                                transition = 3

                                steps = 0
                            End If
                        End If
                    End If
                End If
                directed = (present + 4) Mod 8
                If Not is90 Then
                    v = New Vertex(pr.X, pr.Y)
                End If
                If is90 Then
                    trans_x = 0
                    trans_y = 0
                    transition = 3
                    steps = 0
                End If
                coods.Clear()
                color.Clear()
            End If
        End While

    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        scan()
    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        OpenFileDialog1.ShowDialog()
    End Sub
End Class